Part 8 bis - プロトコル入門

コンテクスト

前回のチュートリアルではPlanについてご紹介しました。今回はProtocolという概念についてです。Protocolは複数のPlanを組み合わせ、リモートワーカーの環境下にデプロイすることができます。デプロイ後は一回のコミュニケーションで実行することができます。

Protocolは複雑な演算処理を複数のワーカーに分散させることができる外観的なオブジェクトです。Protocolの重要な特徴は、ワーカー間で送られたり、検索されたりして、最終的に特定のワーカーにデプロイできる事です。そのため、ユーザーはProtocolをデザインすることで、ワーカーはそれをダウンロード、適用して、プログラムを実行する、なんて事が実現できるのです。

では、見てみましょう。

Authors:

1. 作成とデプロイ

Protocolはworkerplanの組みによって作成されます。workerは実際のワーカーでもワーカーIDでも構いません。planはオブジェクトでもポインタでも構いません。


In [ ]:
import torch as th
import syft as sy
hook = sy.TorchHook(th)

# IMPORTANT: ローカルワーカーはクライアントワーカーにはなれません
hook.local_worker.is_client_worker = False

Planを3つ定義して、Protocolとして纏めてみましょう。機能は全て1を足すオペレーションです。


In [ ]:
@sy.func2plan(args_shape=[(1,)])
def inc1(x):
    return x + 1

@sy.func2plan(args_shape=[(1,)])
def inc2(x):
    return x + 1

@sy.func2plan(args_shape=[(1,)])
def inc3(x):
    return x + 1

protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])

次にProtocolをワーカーにくっつける必要があります。これは.deploy(*workers)コマンドで実行できます。では、ワーカーを作成しましょう。


In [ ]:
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
charlie = sy.VirtualWorker(hook, id="charlie")

In [ ]:
workers = alice, bob, charlie

protocol.deploy(*workers)

各Planはそれぞれ関連づけられたワーカーの元に既に送られています。既にデプロイされているんです。

実は2つのフェーズから成り立っています。第一フェーズはワーカーとPlanの関連付けです。この段階ではワーカーの名前の文字列と関連づけられているだけです。第二フェーズでは、実際に各Planが各ワーカーの元へ送信されます。

2. Protocolの実行

Protocolを実行するというのは、全てのPlanを順番に実行する事と同義です。そのためにやるべき事は、最初のPlanが配置されている場所に入力データを送り込む事だけです。すると最初のPlanは実行され、その結果が次のPlanの入力データとなります。全てのPlanが順次実行され、最後のPlanが完了するとポインタが返されます。


In [ ]:
x = th.tensor([1.0])
ptr = protocol.run(x)
ptr

In [ ]:
ptr.get()

入力された1.0は3つのPlanを通過して3度1がたされ、4になって戻ってきています。

実は、引数にポインタを使ってPlanをリモート実行することも可能です。


In [ ]:
james = sy.VirtualWorker(hook, id="james")

In [ ]:
protocol.send(james)

In [ ]:
x = th.tensor([1.0]).send(james)
ptr = protocol.run(x)
ptr

見ての通り、結果として返されるポインタはJamesがもっていますね。


In [ ]:
ptr = ptr.get()
ptr

In [ ]:
ptr = ptr.get()
ptr

3. Protocolの検索

実運用では、外部からProtocolをダウンロードしてきて、あなたのリモートワーカーにデプロイし、あなたのデータに対して実行したいと思うかもしれません。

それではまだデプロイされていないProtocolを初期化して、リモートワーカーへ送ってみましょう。


In [ ]:
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
protocol.tag('my_protocol')
protocol.send(james)

In [ ]:
me = sy.hook.local_worker # ローカルワーカーをmeとして取得しておきます

ここでProtocolを検索してみましょう。


In [ ]:
responses = me.request_search(['my_protocol'], location=james)
responses

今、Protocolのポインタに対してアクセスできます。


In [ ]:
ptr_protocol = responses[0]

他のポインタと同じように、実態を受け取る事も出来ます。


In [ ]:
protocol_back = ptr_protocol.get()
protocol_back

後は先ほど学んだ手順と同様です。


In [ ]:
protocol_back.deploy(alice, bob, charlie)

x = th.tensor([1.0])
ptr = protocol_back.run(x)
ptr.get()

Protocol関連のより実践的な例はこれから追加される予定ですが、Protocolが持つ可能性については十分に感じて頂けたと思います。

PySyftのGitHubレポジトリにスターをつける

一番簡単に貢献できる方法はこのGitHubのレポジトリにスターを付けていただくことです。スターが増えると露出が増え、より多くのデベロッパーにこのクールな技術の事を知って貰えます。

Slackに入る

最新の開発状況のトラッキングする一番良い方法はSlackに入ることです。 下記フォームから入る事ができます。 http://slack.openmined.org

コードプロジェクトに参加する

コミュニティに貢献する一番良い方法はソースコードのコントリビューターになることです。PySyftのGitHubへアクセスしてIssueのページを開き、"Projects"で検索してみてください。参加し得るプロジェクトの状況を把握することができます。また、"good first issue"とマークされているIssueを探す事でミニプロジェクトを探すこともできます。

寄付

もし、ソースコードで貢献できるほどの時間は取れないけど、是非何かサポートしたいという場合は、寄付をしていただくことも可能です。寄附金の全ては、ハッカソンやミートアップの開催といった、コミュニティ運営経費として利用されます。

OpenMined's Open Collective Page


In [ ]: